package com.letao.server.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.letao.server.dto.BatchShopInfoDTO;
import com.letao.server.dto.EsShopInfoDTO;
import com.letao.server.dto.PageDTO;
import com.letao.server.dto.Result;
import com.letao.server.entity.ShopInfo;
import com.letao.server.mapper.ShopInfoMapper;
import com.letao.server.service.IBaseRegionService;
import com.letao.server.service.IShopService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * 商铺模块功能处理接口实现类
 */
@Slf4j
@Service
public class ShopServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> implements IShopService {
    @Resource
    private ShopInfoMapper shopInfoMapper;
    @Resource
    private RestHighLevelClient client;
    @Resource
    private IBaseRegionService baseRegionService;

    /**
     * 分页查询店铺信息处理函数
     *
     * @param name       店铺名
     * @param provinceId 省份Id
     * @param cityId     城市Id
     * @param districtId 区Id
     * @param page       页码
     * @param pageSize   页大小
     * @return 返回的结果
     */
    @Override
    public Result getPageInfo(Long id, String name, Integer provinceId, Integer cityId, Integer districtId, Integer page, Integer pageSize) {
        // 1.条件查询创建和分页信息创建
        IPage<ShopInfo> shopPage = new Page<>(page, pageSize);
        QueryWrapper<ShopInfo> queryWrapper = new QueryWrapper<>();
        if (id != null) queryWrapper.likeRight("id", id);
        if (name != null) queryWrapper.like("name", name);
        if (provinceId != null) queryWrapper.eq("province_id", provinceId);
        if (cityId != null) queryWrapper.eq("city_id", cityId);
        if (districtId != null) queryWrapper.eq("district_id", districtId);
        // 2.查询
        IPage<ShopInfo> shopInfoIPage = shopInfoMapper.selectPage(shopPage, queryWrapper);

        List<ShopInfo> shopInfoList = shopInfoMapper.selectList(queryWrapper);

        List<BatchShopInfoDTO> batchShopInfoDTOS = new ArrayList<>();

        for (ShopInfo info : shopInfoList) {
            BatchShopInfoDTO batchShopInfoDTO = BeanUtil.copyProperties(info, BatchShopInfoDTO.class);
            batchShopInfoDTO.setProvinceName(baseRegionService.getById(info.getProvinceId()).getName());
            batchShopInfoDTO.setCityName(baseRegionService.getById(info.getCityId()).getName());
            batchShopInfoDTO.setDistrictName(baseRegionService.getById(info.getDistrictId()).getName());
            batchShopInfoDTOS.add(batchShopInfoDTO);
        }
        // 3.构造返回结果
        PageDTO<BatchShopInfoDTO> batchShopInfoPageDTO = new PageDTO<>();
        batchShopInfoPageDTO.setRows(batchShopInfoDTOS);
        batchShopInfoPageDTO.setTotalSize(shopInfoIPage.getTotal());
        batchShopInfoPageDTO.setPages(shopInfoIPage.getPages());
        batchShopInfoPageDTO.setPageSize(shopInfoIPage.getSize());
        batchShopInfoPageDTO.setCurrentPage(shopInfoIPage.getCurrent());
        log.info("管理员批量查询了商铺信息");
        return Result.success(batchShopInfoPageDTO);
    }

    /**
     * 根据坐标推荐商铺
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 返回的结果
     */
    @Override
    public Result suggect(Double longitude, Double latitude) {
        // 1.构造查询请求
        SearchRequest request = new SearchRequest("shop");
        request.source()
                .query(QueryBuilders.matchAllQuery())
                .sort(SortBuilders.geoDistanceSort("location", new GeoPoint(latitude, longitude))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS))
                .size(10);
        SearchResponse search;
        // 2.发送请求
        try {
            search = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 3.解析返回结果
        SearchHits searchHits = search.getHits();
        SearchHit[] hits = searchHits.getHits();
        List<EsShopInfoDTO> list = new ArrayList<>();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            EsShopInfoDTO dto = JSON.parseObject(json, EsShopInfoDTO.class);
            list.add(dto);
        }
        return Result.success(list);
    }
}
